package fun.coding.array;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.tuple.Pair;

import fun.coding.array.ArrayManipulationImpl.MethodType;

public class ArrayMain {

    /**
     * @param args
     */
    public static void main(String[] args) {
        ArrayManipulation am = new ArrayManipulationImpl();
        //int[] a = {3, 0, 1, 0, 0, 9, 0, 7};
//        int[] a = {3, 0, 1, 0, 0, 9, 0, 7};
        //int[] a = {0, 3, 0, 1, 0, 0, 9, 0, 7}; 
     //   am.removeDuplicateAndCondenseArray(a, 0);
     //   am.removeDuplicateAndCondenseArrayBetter(a, 0);
//        
//        int[] b = {3, 4, 4, 4, 2, 2, 3, 3, 3, 3, 3, 4};
//        int max = am.maxSameSubSequence(b);
//        System.out.println(String.format("Max sub sequence is %s", max));
        
       // int[] a1 = {7, 6, 9, 8, 2, 3, 4};
       // am.printMaxSlidingWindow(a1, 3);
        
//        int[] a = {2, 9, 3, 7, 8};
//        System.out.println(am.largestKthElementHeapSolution(a, 3));
        /*
        int[] num = {-1, 0, 1, 2, -1, -4};
        ArrayList<ArrayList<Integer>> l = am.threeSum(num);
        for(ArrayList<Integer> entry : l) {
        	System.out.print("Entry is \t");
        	for(int i : entry) {
        		System.out.print(i + "\t");
        	}
        	System.out.println();
        }
        */
        /*
        int[] a = {3, 5, 7, 9};
        int[] b = {2, 4, 7, 9, 11, 13};
        
        ArrayList<Integer> m = am.mergeTwoSortedArrays(a, b);
        for(int i : m) {
        	System.out.print(i + "\t");
        }
        */
        
        //System.out.print(am.reverse(-0));
        
        /*
        int[] a = {3, 3, 5, 5, 8};
        System.out.println(am.findNumOnlyAppearOnceInPairArray(a));
        */
        /*
        int[] a = {2, 3, 5, 4, 6};
        System.out.println(am.fineMedian(a));
        */
        /*
        int[] a1 = {5, 9, 11, 13, 17};
        int[] a2 = {2, 6, 18, 21};
        System.out.println(am.findKthSmallestInTwoSortedArray(a1, a2, 4));
        
        int[] a3 = {2, 5, 11, 17, 21, 29};
        ArrayList<Integer> res = am.intersectTwoSortedArrays(a1, a3);
      //  printIntegerArrayList(res);
        printArrayList(res);
        ArrayList<String> res1 = new ArrayList<String>();
        res1.add("lady");
        res1.add("gaga");
        printArrayList(res1);
        */
        
        int[] a = {5, 2, 5, 2, 8, 7, 3, 11};
        ArrayList<ArrayList<Integer>> res = am.twoSum(a, 7, MethodType.SORT);
        //printArrayList(res);
        System.out.println(Arrays.asList(res));
       
        /*
        int[] a = {2, 4, 5, 7, 9, 13};
        ArrayList<Integer> res = am.findKNearestNumber(a, 3, 2);
   //     ArrayMain.printArrayList(res);
        System.out.println(Arrays.asList(res));
        */
        ArrayList<ArrayList<Integer>> al = new ArrayList<ArrayList<Integer>>();
        int[] a1 = {2, 3, 5};
        int[] a2 = {1, 8};
        int[] a3 = {4, 6, 7};
        
        ArrayList<Integer> b1 = new ArrayList<Integer>();
        b1.add(2);
        b1.add(3);
        b1.add(5);
        
        ArrayList<Integer> b2 = new ArrayList<Integer>();
        b2.add(1);
        b2.add(8);
        
        ArrayList<Integer> b3 = new ArrayList<Integer>();
        b3.add(4);
        b3.add(6);
        b3.add(7);
        
        al.add(b1);
        al.add(b2);
        al.add(b3);
        /*
        printArrayList(al);
        ArrayList<Integer> res = am.mergeNSortedArray(al);
        printIntegerArrayList(res);
        */
        //System.out.println(Arrays.asList(am.reservoirSampling(1000, 10)));
        /*
        int[] temp = am.reservoirSampling(1000, 10);
        
        for(int i : temp) {
        	System.out.print(i + ", ");
        }
        */
        /*
        int[] array = {5, 7, 6, 4, 9, 10, 2, 1};
      //  int[] array = {1, 2, 4, 1};
        System.out.println("interval is ");
        am.printIntervalsArray(array);
        
        
        int [] aa = {3, 4, 5, 2,
                7, 2, 1, 9,
                4, 9, 6, 5};
        
        int[] result = am.copyArray(aa, 0, 0, 1, 1, 3, 2, 4, 3);
        
        for(int i : result) {
            System.out.print(i + ",");
        }
*/
        
      //  int[][] matrix = {{1}, {2}, {3}};
     //   int[][] matrix = {{1}};
/*    int[][]  matrix = {   {1, 2, 3},
                 {8, 9, 4}, 
                 {7, 6, 5}};
        for(int[] row : matrix) {
            for(int i : row)
                System.out.print(i + ",");
            System.out.println();
        }
    
       am.printSpiralMatrix(matrix);
        
            
        System.out.println("3 way median");
        System.out.println(am.find3Median(3, 1, 2));
        
        int[] rotateArray = {1, 2, 3, 4, 5, 6};
        am.rotateArrays(rotateArray, 3);*/
        //am.rotateArraysBetter(rotateArray, 3);
    
        
        ArrayList<Pair<Integer, Integer>> test = new ArrayList<Pair<Integer, Integer>>();
        test.add(Pair.of(6, 2));
        test.add(Pair.of(6, 3));
        test.add(Pair.of(-6, 4));
        test.add(Pair.of(6, 0));
        test.add(Pair.of(6, 7));
        test.add(Pair.of(0, 7));
        test.add(Pair.of(6, -4));
        test.add(Pair.of(-6, -4));
        test.add(Pair.of(6, 4));
        test.add(Pair.of(7, 1));
        
        for (Pair<Integer, Integer> pair : test) {
      //      System.out.println(pair.getLeft() + " divided by " + pair.getRight() + " is " + am.divideWithSubtraction(pair.getLeft(), pair.getRight()));
            System.out.println(pair.getLeft() + " divided by " + pair.getRight() + " is " + am.divideWithoutSubtraction(pair.getLeft(), pair.getRight()));
        }
        /*
        ArrayList<int[]> test = new ArrayList<int[]>();
        int[] t = {2,1,5,6,2,3};
        test.add(t);
        
        for (int[] it : test) {
            System.out.println(am.largestRectangleAreaONSquare(it));
        }
        */
        
        System.out.println(am.findPrimes(14));
        
    }
    
    // Note: I am so tacky... use Arrays.asList(Collection), it will do this
    // Note from effective java, use standard library instead of implement your own buggy one. 
    public static void printIntegerArrayList(ArrayList<Integer> list) {
        for(int i : list) {
            System.out.print(i + "\t");
        }
        System.out.println();
    }
    public static void printArrayList(ArrayList<?> list) {
        for(Object o : list) {
            if(o instanceof Collection) {
                for(Object oo : (Collection)o) {
                    System.out.print(oo + "\t");
                }
                System.out.println();
            }
            else {
                System.out.print(o + "\t");
            }
        }
        System.out.println();
    }

}
